package com.ruoyi.common.base.biz.service.biz;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.base.biz.service.base.BaseService;
import com.ruoyi.common.base.biz.service.extend.BaseExtendService;
import com.ruoyi.common.core.domain.BizBaseEntity;
import com.ruoyi.common.utils.paging.PageInfoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * BizBaseServiceImpl
 *
 * @author ZhengJun
 * @since 2023/6/7 22:31
 */
public class BaseBizServiceImpl<E extends BizBaseEntity, Req extends Do, Res extends Po, Do extends E, Po extends E,
        S extends BaseService<E, Do, Po>, ExtendS extends BaseExtendService<E, Do, Po>>
        implements BaseBizService<E, Req, Res>
{
    @Autowired
    protected S service;
    @Autowired
    protected ExtendS extendService;

    protected Class<Res> resClass = currentResClass();

    @Override
    public PageInfo<Res> paging(Req req)
    {
        this.beforePage(req);
        PageInfo<Po> pageInfoPo = this.getService().pagingPoByDo(req);
        PageInfo<Res> pageInfoRes = PageInfoUtils.toPageInfoRes(pageInfoPo, resClass);
        this.afterPage(pageInfoRes.getList());
        return pageInfoRes;
    }

    /**
     * 装维pageInfo
     *
     * @param pagePo 分页列表
     * @return 结果列表
     */
    protected PageInfo<Res> toPageInfo(List<Po> pagePo)
    {
        List<Res> resList = BeanUtil.copyToList(pagePo, resClass);
        PageInfo<Res> resPageInfo = new PageInfo<>(resList);
        BeanUtil.copyProperties(pagePo, resPageInfo);
        return resPageInfo;
    }

    /** 分页前置方法 */
    protected void beforePage(Req req)
    {
    }

    /**
     * 分页后置方法
     *
     * @param resList 结果集列表
     */
    protected void afterPage(List<Res> resList)
    {
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeByIdList(List<Long> idList)
    {
        this.beforeRemove(idList);
        boolean result = this.getService().removeByIds(idList);
        if (result) {
            this.afterRemove(idList);
        }
        return result;
    }

    /** 删除后置方法 */
    protected void afterRemove(List<Long> idList)
    {
    }

    /** 删除前置方法 */
    protected void beforeRemove(List<Long> idList)
    {
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean update(Req req)
    {
        this.getExtendService().getByIdNotNull(req.getId());
        this.beforeUpdate(req);
        boolean result = this.getService().updateById(req);
        if (result) {
            this.afterUpdate(req);
        }
        return result;
    }

    /** 修改后置方法 */
    protected void afterUpdate(Req req)
    {
    }

    /** 修改前置方法 */
    protected void beforeUpdate(Req req)
    {
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(Req req)
    {
        this.beforeSave(req);
        boolean result = this.getService().save(req);
        if (result) {
            this.afterSave(req);
        }
        return result;
    }

    /** 新增后置方法 */
    protected void afterSave(Req req)
    {
    }

    /** 新增前置方法 */
    protected void beforeSave(Req req)
    {
    }

    @Override
    public List<Res> list(Req req)
    {
        this.beforeList(req);
        List<Po> poList = this.getService().listPoByDo(req);
        List<Res> resList = BeanUtil.copyToList(poList, resClass);
        this.afterList(resList, req);
        return resList;
    }

    /** 列表前置方法 */
    protected void beforeList(Req req)
    {
    }

    /**
     * 列表后置方法
     *
     * @param resList 结果集
     */
    protected void afterList(List<Res> resList, Req req)
    {
        afterList(resList);
    }

    /**
     * 列表后置方法
     *
     * @param resList 结果集
     */
    protected void afterList(List<Res> resList)
    {
    }

    @Override
    public Res getById(Long id)
    {
        this.beforeGetById(id);
        Po po = this.getExtendService().getPoByIdNotNull(id);
        Res res = BeanUtil.toBean(po, resClass);
        this.afterGetById(res);
        return res;
    }

    /** 获取详情前置方法 */
    protected void beforeGetById(Long id)
    {
    }

    /**
     * 获取详情后置方法
     *
     * @param res 结果集
     */
    protected void afterGetById(Res res)
    {
    }

    protected S getService()
    {
        return service;
    }

    protected ExtendS getExtendService()
    {
        return extendService;
    }

    protected Class<Res> currentResClass()
    {
        return (Class<Res>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseBizServiceImpl.class, 2);
    }
}
